#!/var/www/webapp/bin/python
"""The CherryPy daemon."""

import sys

import cherrypy
from cherrypy.process import plugins


class Cherryd:
  
  def configure(self, configfiles = None, environment = None):
    for c in configfiles or []:
      cherrypy.config.update(c)
      # If there's only one app mounted, merge config into it.
      if len(cherrypy.tree.apps) == 1:
        for app in cherrypy.tree.apps.values():
          if isinstance(app, cherrypy.Application):
            app.merge(c)
    
    if environment is not None:
      try:
        cherrypy.config.update({'environment' : environment})
      except KeyError:
        pass # allow environments undefined in cherrypy._cpconfig.environments 
  
  def include(self, imports = None, paths = None):
    sys.path = [''] + sys.path
    for p in paths or []:
      sys.path.insert(0, p)
    
    for i in imports or []:
      exec("import %s" % i)
  
  def run(self, daemonize = None, pidfile = None, user = None, group = None):
    engine = cherrypy.engine
    
    if daemonize:
      # Don't print anything to stdout/sterr.
      cherrypy.config.update({'log.screen' : False})
      plugins.Daemonizer(engine).subscribe()
    
    if pidfile:
      plugins.PIDFile(engine, pidfile).subscribe()
    
    if user or group:
      plugins.DropPrivileges(engine, uid = user, gid = group).subscribe()
    
    
    if hasattr(engine, "signal_handler"):
      engine.signal_handler.subscribe()
    if hasattr(engine, "console_control_handler"):
      engine.console_control_handler.subscribe()
    
    # Always start the engine; this will start all other services
    try:
      engine.start()
    except:
      # Assume the error has been logged already via bus.log.
      sys.exit(1)
    else:
      engine.block()


if __name__ == '__main__':
  from optparse import OptionParser
  
  parser = OptionParser()
  options = (
    ('-c', '--config',      {"action"  : "append"},     "specify config file(s)"),
    ('-d', '--daemonize',   {"action"  : "store_true"}, "run the server as a daemon"),
    ('-u', '--user',        {"default" : None},         "run the server as user"),
    ('-g', '--group',       {"default" : None},         "run the server as group"),
    ('-e', '--environment', {"default" : None},         "apply the given config environment"),
    ('-i', '--include',     {"action"  : "append"},     "specify modules to import"),
    ('-p', '--pid',         {"default" : None},         "store the process id in the given file"),
    ('-P', '--path',        {"action"  : "append"},     "add the given paths to sys.path")
  )
  for option in options:
    parser.add_option(option[0], option[1], dest = option[1][2:], help = option[3], **option[2])
  
  
  cherryd = Cherryd()
  
  options, args = parser.parse_args()
  if options.config or options.environment:
    cherryd.configure(options.config, options.environment)
  if options.path or options.include:
    cherryd.include(options.include, options.path)
  
  cherryd.run(options.daemonize, options.pid, options.user, options.group)